#ifndef _SYS_OP_H
#define _SYS_OP_H
#include <linux/kernel.h>  // sprintf
#include <linux/kobject.h>
#include <linux/string.h>
#include <linux/sysfs.h>

#include "list_op.h"

#define LTCS_TRUSTED_SECURITYFS_DIR      "securityfs"
#define LTCS_TRUSTED_SECURITYFS_LTCS_DIR "ltcs"
#define LTCS_TRUSTED_FILE                "trusted_elf"

struct kobject* securityfs_dir;
struct kobject* securityfs_ltcs_dir;

// read sysfs
ssize_t ltcs_show(struct kobject* kobj, struct kobj_attribute* attr, char* buf)
{
    ssize_t                   ret = 0;
    struct trusted_elf_entry* entry;

    entry = ltcs_list_del_entry();
    if (!entry) return ret;
    ret = sprintf(buf, "%s", entry->file_name);
    ltcs_list_free_entry(entry);

#ifdef DEBUG
    ltcs_list_print_list();
#endif
    return ret;
}

// write sysfs
ssize_t ltcs_store(struct kobject* kobj, struct kobj_attribute* attr,
                   const char* buf, size_t count)
{
    struct trusted_elf_entry* entry;
    char*                     store_buf;

    entry = kzalloc(sizeof(struct trusted_elf_entry), GFP_KERNEL);
    if (!entry) {
        debug_info("alloc memery for trusted_elf_entry failed.\n");
        return count;
    }
    store_buf = kzalloc(count, GFP_KERNEL);
    if (!store_buf) {
        debug_info("alloc memery for store_buf failed.\n");
        kfree(entry);
        return count;
    }

    strncpy(store_buf, buf, count);
    entry->file_name = store_buf;
    ltcs_list_add_entry(entry);
#ifdef DEBUG
    ltcs_list_print_list();
#endif
    return count;
}

static struct kobj_attribute ltcs_status_attr = {
    .attr  = {.name = LTCS_TRUSTED_FILE, .mode = 0600},
    .show  = &ltcs_show,   // 读节点
    .store = &ltcs_store,  // 写节点
};

static struct attribute* ltcs_attr[] = {
    &ltcs_status_attr.attr,  // ltcs_status_attr的属性
    NULL,
};

static struct attribute_group ltcs_attr_group = {
    .attrs = ltcs_attr,  // 节点组ltcs_attr_group，包含ltcs_attr
};

static int ltcs_sysfs_init(void)
{
    int ret        = 0;
    securityfs_dir = kobject_create_and_add(
        LTCS_TRUSTED_SECURITYFS_DIR,
        kernel_kobj);  // kernel_kobj:系统定义变量，表示/sys/kernel目录.
    if (!securityfs_dir) {
        debug_info("create /sys/kernel%s failed.\n",
                   LTCS_TRUSTED_SECURITYFS_DIR);
        return 1;
    }

    securityfs_ltcs_dir = kobject_create_and_add(
        LTCS_TRUSTED_SECURITYFS_LTCS_DIR, securityfs_dir);
    if (!securityfs_ltcs_dir) {
        debug_info("create /sys/kernel%s failed.\n",
                   LTCS_TRUSTED_SECURITYFS_LTCS_DIR);
        return 1;
    }

    ret = sysfs_create_group(securityfs_ltcs_dir, &ltcs_attr_group);
    if (ret) {
        debug_info("create /sys/kernel/%s/%s/%s failed\n",
                   LTCS_TRUSTED_SECURITYFS_DIR,
                   LTCS_TRUSTED_SECURITYFS_LTCS_DIR, LTCS_TRUSTED_FILE);
        kobject_put(securityfs_ltcs_dir);
        kobject_put(securityfs_dir);
        return ret;
    }

    debug_info("ltcs fs init\n");
    return ret;
}

static void ltcs_sysfs_free(void)
{
    sysfs_remove_group(securityfs_ltcs_dir, &ltcs_attr_group);
    kobject_put(securityfs_ltcs_dir);
    kobject_put(securityfs_dir);
    debug_info("ltcs fs free\n");
    return;
}

#endif /* _SYS_OP_H */
